package factory;

import java.util.HashMap;

import loadsave.LoadSaveable;
import loadsave.Memento;
import loadsave.loadsaveobject.Iterator;
import loadsave.loadsaveobject.LoadSaveMapComposite;
import loadsave.loadsaveobject.LoadSaveObject;
import loadsave.loadsaveobject.LoadSaveObjectComposite;
import loadsave.loadsaveobject.LoadSavePrimitive;
import skills.ActiveSkill;
import skills.DetectTrapSkill;
import skills.PickpocketSkill;
import skills.RemoveTrapSkill;
import skills.Skill;

public class SkillFactory implements LoadSaveable {
	private static HashMap<String, Skill> interactiveSkills;
	private static HashMap<String, ActiveSkill> activeSkills;
	
	/**
	 * create the static maps
	 */
	static {
		interactiveSkills = new HashMap<String, Skill>();
		activeSkills = new HashMap<String, ActiveSkill>();
	}

	/**
	 * put an interactive skill in the map
	 * @param s
	 */
	public static void addInteractiveSkill(Skill s) {
		interactiveSkills.put(s.getName(), s);
	}
	
	/**
	 * put an active skill in the map
	 * @param as
	 */
	public static void addActiveSkill(ActiveSkill as) {
		activeSkills.put(as.getName(), as);
	}
	
	/**
	 * return an activeskill based on the loadsaveobject
	 */
	public static ActiveSkill createActiveSkill(LoadSaveObject lso) {
		return activeSkills.get(lso.get("name")).clone();
	}
	
	/**
	 * return an activeskill based on the string
	 * @param name
	 * @return
	 */
	public static ActiveSkill createActiveSkill(String name) {
		if( activeSkills.containsKey(name) ) {
			return activeSkills.get(name).clone();
		}
		return null;
	}
	
	/**
	 * return a skill based on the loadsaveobject
	 * @param lso
	 * @return
	 */
	public static Skill createSkill(LoadSaveObject lso) {
		if (interactiveSkills.containsKey(lso.get("name")))
			return interactiveSkills.get(lso.get("name")).clone();
		return createActiveSkill(lso);
	}
	
	/**
	 * return a skill based on the name string
	 * @param name
	 * @return
	 */
	public static Skill createSkill(String name) {
		if (interactiveSkills.containsKey(name))
			return interactiveSkills.get(name).clone();
		return activeSkills.get(name).clone();
	}
	
	@Override
	public Memento getMemento() {
		return new Memento() {

			@Override
			public LoadSaveObject getState() {
				LoadSaveObjectComposite toReturn = new LoadSaveObjectComposite("skillFactory", "SkillFactory");
				LoadSaveMapComposite lsmc = new LoadSaveMapComposite("interactiveSkills", "HashMap", "String", "Skill");
				for (String s : interactiveSkills.keySet()) {
					lsmc.add(new LoadSavePrimitive("","",s), interactiveSkills.get(s).getMemento().getState());
				}
				toReturn.add(lsmc.getName(), lsmc);
				lsmc = new LoadSaveMapComposite("activeSkills", "HashMap", "String", "ActiveSkill");
				for (String s : activeSkills.keySet()) {
					lsmc.add(new LoadSavePrimitive("","",s), activeSkills.get(s).getMemento().getState());
				}
				toReturn.add(lsmc.getName(), lsmc);
				return toReturn;
			}

			@Override
			public void restoreState(LoadSaveObject lso) {
				//Again, reflection would be nice here...
				HashMap<String, Skill> skillTypeMap = new HashMap<String, Skill>();
				skillTypeMap.put("ActiveSkill", new ActiveSkill());
				skillTypeMap.put("DetectTrapSkill", new DetectTrapSkill());
				skillTypeMap.put("PickpocketSkill", new PickpocketSkill());
				skillTypeMap.put("RemoveTrapSkill", new RemoveTrapSkill());

				SkillFactory.interactiveSkills = new HashMap<String, Skill>();
				Iterator<LoadSaveObject> i = lso.get("interactiveSkills").getIterator();
				for (i.init(); i.hasNext(); i.next()) {
					Skill toAdd = skillTypeMap.get(i.getCurrKey().getType()).clone();
					toAdd.getMemento().restoreState(i.getCurrVal());
					SkillFactory.interactiveSkills.put(toAdd.getName(), toAdd);
				}
				SkillFactory.activeSkills = new HashMap<String, ActiveSkill>();
				i = lso.get("activeSkills").getIterator();
				for (i.init(); i.hasNext(); i.next()) {
					ActiveSkill toAdd = new ActiveSkill();
					toAdd.getMemento().restoreState(i.getCurrVal());
					SkillFactory.activeSkills.put(toAdd.getName(), toAdd);
				}
			}
		};
	}	
}